package juc.executors;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class CompletableFutureExample5 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //getNow1();
        //complete1();
        //testJoin();
        //completeExceptionally();
        //obtrudeException();

        CompletableFuture<String> future = errorHandle();
        future.whenComplete((v,t)->System.out.println(v));

        Thread.currentThread().join();
    }

    private static void getNow1() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            timeSleep(3);
            return "hello";
        });
        String result = future.getNow("world");
        System.out.println(result);
        System.out.println(future.get());
    }

    private static void complete1() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            //timeSleep(3);
            System.out.println("i will be still process");
            return "hello";
        });
        timeSleep(1);
        //先执行的话，直接以complete的结果为准，忽略CompletableFuture.supplyAsync的get计算结果
        boolean b = future.complete("world");
        //返回complete()后的值
        System.out.println(future.get());
    }

    private static void testJoin() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            timeSleep(3);
            System.out.println("i will be still process");
            return "hello";
        });
        String result = future.join();
        System.out.println(result);
    }

    private static void completeExceptionally() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            //timeSleep(3);
            System.out.println("i will be still process");
            return "hello";
        });
        timeSleep(1);
        future.completeExceptionally(new RuntimeException("error"));
        System.out.println(future.get());
    }

    private static void obtrudeException() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            //timeSleep(3);
            System.out.println("i will be still process");
            return "hello";
        });
        timeSleep(1);
        future.obtrudeException(new RuntimeException("error"));
        System.out.println(future.get());
    }

    private static CompletableFuture<String> errorHandle() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            timeSleep(3);
            System.out.println("i will be still process");
            return "hello";
        });
        future.thenApply(s -> {
            Integer.parseInt(s);
            System.out.println(" keep move");
            return s + "world";
        }).exceptionally(Throwable::getMessage).thenAccept(System.out::println);
        return future;
    }

    /**
     * sleep the specify seconds
     */
    private static void timeSleep(long time) {
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
